using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.IO.Ports;
using System;
using UnityEngine.UI;
//using LibUsbDotNet.DeviceNotify;
using System.Threading;
using System.Management;
using UnityEngine.Events;
[Serializable]
public class StringEvent : UnityEvent<String> { }
/// <summary>
/// 串口连接类,负责连接下位机,收发数据
/// </summary>
public class serial : MonoBehaviour
{
    /// <summary>
    /// 传感器连接状态
    /// </summary>
    public enum SENSOR_CONNECTION
    {
        OK = 1,
        DISCONNECT = 0,
        CONNECTING = 2,

    }
    public Dropdown comList;
    public connectState connectState;
    public StringEvent serialReceiveFunction;

    private SerialPort serialPort;
    private Thread readThread;
    // private IDeviceNotifier UsbDeviceNotifier;
    private SENSOR_CONNECTION state = SENSOR_CONNECTION.DISCONNECT;


    void Awake()
    {
        // UsbDeviceNotifier = DeviceNotifier.OpenDeviceNotifier();
        // UsbDeviceNotifier.OnDeviceNotify += OnDeviceNotifyEvent;
        serialPort = new SerialPort();
        serialPort.NewLine = "\n";
        serialPort.ErrorReceived += new SerialErrorReceivedEventHandler(SerialErrorReceived);

    }
    // Start is called before the first frame update
    void Start()
    {
        //Debug.Log(getCOMList().ToString());

        getCOMList();
        if (comList.options.Count != 0)
        {
            comList.captionText.text = comList.options[0].text;
        }
    }

    // Update is called once per frame
    void Update()
    {
    }
    void OnDestroy()
    {
        // UsbDeviceNotifier.Enabled = false;  // Disable the device notifier

        // Unhook the device notifier event
        // UsbDeviceNotifier.OnDeviceNotify -= OnDeviceNotifyEvent;
        disconnectSensor();
    }
    /// <summary>
    /// 获取已经连接的COM口
    /// </summary>
    /// <returns>COM口string[] </returns>
    public string[] getCOMList()
    {
        string[] ports = SerialPort.GetPortNames();
        Debug.Log("The following serial ports were found:");

        // Display each port name to the console.
        foreach (string port in ports)
        {
            Debug.Log(port);
            comList.options.Add(new Dropdown.OptionData(port));
        }
        return ports;
    }
    /// <summary>
    /// 传感器开关,连接或断开传感器
    /// </summary>
    /// <param name="com"></param>
    public void sensorSwitch()
    {
        if (state == SENSOR_CONNECTION.OK)
        {
            disconnectSensor();
        }
        else if (state == SENSOR_CONNECTION.DISCONNECT)
        {

            connectSensor(comList.captionText.text.ToString());
        }
    }
    /// <summary>
    /// 连接到传感器
    /// </summary>
    /// <param name="com">com口</param>
    public void connectSensor(string com)
    {
        // view.onViewSetSerialState(SENSOR_CONNECTION.CONNECTING);
        state = SENSOR_CONNECTION.CONNECTING;

        serialPort.PortName = com;
        serialPort.BaudRate = 115200;  //波特率，默认9600
        serialPort.DataBits = 8;  //数据位，默认8
        serialPort.StopBits = System.IO.Ports.StopBits.One;  //停止位，默认 System.IO.Ports.StopBits.One
        serialPort.Parity = System.IO.Ports.Parity.None;  //奇偶校验，默认 System.IO.Ports.Parity.None
                                                          //serialPort.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);
        try
        {
            serialPort.Open();
            // view.onViewSetSerialState(SENSOR_CONNECTION.OK);
            state = SENSOR_CONNECTION.OK;

            readThread = new Thread(receiveData);

            readThread.Start();


        }
        catch (System.IO.IOException e)
        {
            Debug.Log(e.ToString());
            state = SENSOR_CONNECTION.DISCONNECT;
            // view.onViewSetSerialState(state);
            // view.onViewDisplayError(e);

        }
    }
    /// <summary>
    /// 断开与传感器的连接
    /// </summary>
    public void disconnectSensor()
    {
        try
        {
            serialPort.Close();


        }
        catch (Exception e)
        {
            Debug.Log(e.ToString());
            // view.onViewDisplayError(e);

        }
        finally
        {
            state = SENSOR_CONNECTION.DISCONNECT;
            // view.onViewSetSerialState(SENSOR_CONNECTION.DISCONNECT);

        }
    }
    /// <summary>
    /// 获取传感器的连接状态
    /// </summary>
    /// <returns></returns>
    public SENSOR_CONNECTION getSensorConnection()
    {
        return state;
    }

    /// <summary>
    /// 当由新的USB插入或者拔出时,会调用此函数,用于更新com口列表
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    // private void OnDeviceNotifyEvent(object sender, DeviceNotifyEventArgs e)
    // {
    //     //事件发生  

    //     Debug.Log(e.ToString());//将事件输出  
    //     // view.onViewSetCOMPorts(getCOMList());
    // }


    /// <summary>
    /// 发送数据到下位机
    /// </summary>
    /// <param name="str">字符串数据</param>
    public void sendString(string str)
    {
        if (serialPort.IsOpen)
            serialPort.Write(str + "\r\n");
    }
    /// <summary>
    /// 读取数据线程，该线程会根据下位机发送的数据更新传感器数据数组并更新ui数据
    /// </summary>
    private void receiveData()
    {
        Debug.Log("receiveData");
        while (state == SENSOR_CONNECTION.OK && serialPort.IsOpen)
        {
            try
            {

                string s = serialPort.ReadLine();

                //Debug.Log(s);
                Loom.QueueOnMainThread((param) =>
                {
                    serialReceiveFunction.Invoke(s);
                }, null);

                //analysisString(serialPort.ReadLine());
            }
            catch (System.Exception e)
            {
                //serialPort.Close();
                Debug.Log(e);

                state = SENSOR_CONNECTION.DISCONNECT;
                // view.onViewSetSerialState(state);
            }

        }

    }
    /// <summary>
    /// 错误发生时的回调函数
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void SerialErrorReceived(object sender, SerialErrorReceivedEventArgs e)
    {
        Debug.Log(e.ToString());
        state = SENSOR_CONNECTION.DISCONNECT;

    }

}
